package com.zzoranor.presentationserver;

import java.io.*;
import java.net.*;

import protocols.ProtocolsProto.AddCharacter;
import protocols.ProtocolsProto.CharacterMessage;
import protocols.ProtocolsProto.ClientToServerMessage;
import protocols.ProtocolsProto.HelloWorld;
import protocols.ProtocolsProto.ServerToClientMessage;

import com.zzoranor.util.Log;

public class ChatClient

{

	public static final String SERVER_HOSTNAME = "localhost";

	public static final int SERVER_PORT = 1234;

	public static void main(String[] args)

	{

		DataInputStream in = null;
		DataOutputStream out = null;

		try {

			// Connect to Nakov Chat Server

			Socket socket = new Socket(SERVER_HOSTNAME, SERVER_PORT);
			in = new DataInputStream(socket.getInputStream());
			out =new DataOutputStream(socket.getOutputStream());
			System.out.println("Connected to server " + SERVER_HOSTNAME + ":" + SERVER_PORT);

		} catch (IOException ioe) {
			System.err.println("Can not establish connection to " +	SERVER_HOSTNAME + ":" + SERVER_PORT);
			ioe.printStackTrace();
			System.exit(-1);

		} 

		// Create and start Sender thread

		Sender sender = new Sender(out);

		sender.setDaemon(true);

		sender.start();

		try {

			// Read messages from the server and print them
			while(true)
			{
				byte size = (byte) in.read();
				if(size == -1)
				{
					// EOF
					break;
				}
				byte [] bytes = new byte[size];
				in.readFully(bytes);
				
				ServerToClientMessage message = ServerToClientMessage.parseFrom(bytes);
				//HelloWorld hw = message.getHelloWorld();
				System.out.println(message.toString());
			}
			
		} catch (IOException ioe) {

			System.err.println("Connection to server broken.");

			ioe.printStackTrace();

		}finally
		{
			if(in != null)
			{
				try {
					in.close();
				} catch (IOException e) {
					//e.printStackTrace();
				}
			}
			if(out != null)
			{
				try {
					out.close();
				} catch (IOException e) {
					//e.printStackTrace();
				}
			}
		}

	}

}

class Sender extends Thread

{

	private DataOutputStream mOut;

	public Sender(DataOutputStream aOut)

	{

		mOut = aOut;

	}

	/**
	 * 
	 * Until interrupted reads messages from the standard input (keyboard)
	 * 
	 * and sends them to the chat server through the socket.
	 */

	public void run()

	{

		BufferedReader in = null;
		try {

			in = new BufferedReader(new InputStreamReader(
					System.in));

			while (!isInterrupted()) {
				
				String message = in.readLine();
				String[] tokens = message.split(" ");
				CharacterMessage cMessage = null;
				if(tokens.length > 1)
				{
					if(tokens[0].equals("addCharacter"))
					{
						String name = tokens[1];
						cMessage = CharacterMessage.newBuilder()
						.setAddCharacter(
								AddCharacter.newBuilder()
									.setCharName(name)
									.build()
								)
								.build();
					}else
					{
						cMessage = CharacterMessage.newBuilder()
						.setAddCharacter(
								AddCharacter.newBuilder()
								.build()
							)
							.build();
					}
				}
				
				ClientToServerMessage msg = null;
				
				if(cMessage == null)
				{
					msg = ClientToServerMessage.newBuilder()
					.setHelloWorld(
							HelloWorld.newBuilder().
							setHelloWorld(message).
							build()
							)
					.build();
				}else
				{
					msg = ClientToServerMessage.newBuilder()
					.setHelloWorld(
							HelloWorld.newBuilder()
							.setHelloWorld(message)
							.build()
							)
					.setCharacterMessage(cMessage)
					.build();
				}
				
				byte size = (byte) msg.getSerializedSize();
				mOut.writeByte(size);
				mOut.write(msg.toByteArray());
			}

		} catch (IOException ioe) {
			// Communication is broken
			Log.e("IOException Caught in Chatclient. ");
			ioe.printStackTrace();
		}finally
		{
			if(in != null)
			{
				try {
					in.close();
				} catch (IOException e) {
					//e.printStackTrace();
				}
			}
			if(mOut != null)
			{
				try {
					mOut.close();
				} catch (IOException e) {
					//e.printStackTrace();
				}
			}
		}

	}

}
